home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Games / Arashi 1.1.1 / source code / Game Source / jam src / STFlipper.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-01-13  |  10.5 KB  |  427 lines  |  [TEXT/KAHL]

  1. /*/
  2.      Project Arashi: STFlipper.c
  3.      Major release: Version 1.1d2, 9/5/95
  4.  
  5.      Last modification: Thursday, January 13, 1994, 7:31
  6.      Created: Sunday, February 12, 1989, 22:58
  7.  
  8.      Copyright © 1989-1994, Juri Munkki
  9. /*/
  10.  
  11. #include "VA.h"
  12. #include "STORM.h"
  13. #include "STCrack.h"
  14.  
  15. #define    MAXFLIPPERS        20
  16. #define    FLIPPERCOLOR    (ThisLevel.flColor)
  17. #define    FLIPPERROTSPEED    (ThisLevel.flRot)
  18. #define    FLIPPERUPSPEED    (ThisLevel.flSpeed)
  19.  
  20. typedef    struct
  21. {
  22.     int        state;        /*    star=0, inactive=1, active=2        */
  23.     int        lane;        /*    Actual lane number                    */
  24.     IFixed    level;
  25.     int        vertex;        /*    vertex currently connected to        */
  26.     int        mirror;        /*    Draw mirror image?                    */
  27.     int        rotation;    /*    Current rotation of flipper            */
  28.     int        direction;    /*    Rotation direction                    */
  29. }    Flipper,*FlipperPtr;
  30.  
  31. enum    {    star, inactive, active    };
  32.  
  33. Flipper    *Flippers;        /*    Pointer to an array of flippers.    */
  34. int        ActiveFlippers;    /*    The number of active flippers.        */
  35.  
  36. extern    Player    Hero;    /*    Player status record.                */
  37.  
  38. /*
  39. >>    Given a connecting point (cx,cy) and a vector (dx,dy)
  40. >>    a flipper shape is drawn as quickly as possible.
  41. */
  42. void    DrawFlipper(cx,cy,dx,dy)
  43. int        cx,cy,dx,dy;
  44. {
  45.     register    int    x1,y1,x2,y2;
  46.                 int    dx4,dx8,dy4,dy8;
  47.     
  48.     VA.color=FLIPPERCOLOR;
  49.     dx4=dx >> 2;        dy4=dy >> 2;    /*    Precalculate some values.    */
  50.     dx8=dx >> 3;        dy8=dy >> 3;
  51.     x1=cx+dx;            y1=cy+dy;
  52.     VAMoveTo(cx,cy);
  53.     x2=dx8-dy4;            y2=dy8+dx4;
  54.     VALineTo(x1-x2,y1-y2);
  55.     x2=dx4-dy8;            y2=dy4+dx8;
  56.     VALineTo(x1-x2,y1-y2);
  57.     VALineTo(x1,y1);
  58.     x2=dx8+dy4;            y2=dy8-dx4;
  59.     VALineTo(cx+x2,cy+y2);
  60.     x2=dx4+dy8;            y2=dy4-dx8;
  61.     VALineTo(cx+x2,cy+y2);
  62.     VALineTo(cx,cy);
  63. }
  64.  
  65. /*
  66. >>    Create a newborn flipper. A flipper appears
  67. >>    as one of the center stars, so the lane or
  68. >>    vertex is decided when the star touches the
  69. >>    playfield. Some of this stuff could just as 
  70. >>    well be done at that time.
  71. */
  72. void    CreateNewFlipper()
  73. {
  74.     register    Flipper        *theflip;
  75.  
  76.     if(ActiveFlippers<MAXFLIPPERS)
  77.     {    theflip=Flippers;
  78.         while(theflip->state!=inactive)
  79.         {    theflip++;
  80.         }
  81.         theflip->state=star;
  82.         theflip->lane=0;
  83.         theflip->level.f=0;
  84.         theflip->level.i=DEPTH;
  85.         theflip->mirror=0;
  86.     
  87.         theflip->direction= (VARandom()<0)?FLIPPERROTSPEED:
  88.                                         -FLIPPERROTSPEED;
  89.         StarApproach(&(theflip->state),FLIPPERCOLOR);
  90.         ActiveFlippers++;
  91.     }
  92. }
  93. /*
  94. >>    This routine creates two flippers from a destroyed
  95. >>    tanker.
  96. */
  97. void    CreateSplitFlippers(lane,level)
  98. int        lane,level;
  99. {
  100.     register    int            i,delta,nextseg,prevseg;
  101.     register    Flipper        *theflip;
  102.  
  103.  
  104.     for(i=0;i<2;i++)
  105.     {    if(ActiveFlippers<MAXFLIPPERS)
  106.         {    theflip=Flippers;
  107.             while(theflip->state!=inactive)
  108.             {    theflip++;
  109.             }
  110.             theflip->vertex= lane+i;
  111.             if(theflip->vertex>=ww.numsegs)
  112.                 theflip->vertex-=ww.numsegs;
  113.  
  114.             theflip->state= active;
  115.             theflip->level.f=0;
  116.             theflip->level.i=level;
  117.             theflip->mirror=0;
  118.         
  119.             theflip->direction= i ? FLIPPERROTSPEED : -FLIPPERROTSPEED;
  120.             
  121.             nextseg=NextSeg[theflip->vertex];
  122.             prevseg=PrevSeg[theflip->vertex];
  123.  
  124.             delta=nextseg-prevseg;
  125.             if(delta<0) delta+=ANGLES;
  126.             
  127.             if(theflip->direction < 0)
  128.             {    theflip->rotation=NextSeg[theflip->vertex]-delta/2;
  129.             }
  130.             else
  131.             {    theflip->rotation=PrevSeg[theflip->vertex]+delta/2;
  132.             }
  133.  
  134.             theflip->lane=LaneSel[theflip->vertex][theflip->rotation];
  135.  
  136.             ActiveFlippers++;
  137.         }
  138.     }
  139. }
  140. /*
  141. >>    A flipper moves by rotating from one vertex
  142. >>    to another. It "grabs" onto the vertex while
  143. >>    rotating, so at times it needs to change
  144. >>    the way it touches. The mirror value is
  145. >>    used for properly drawing the flipper when
  146. >>    this change happens.
  147. */
  148. void    SegSkip(theflip)
  149. register
  150. FlipperPtr    theflip;
  151. {
  152.     theflip->rotation+=ANGLES/2;
  153.     if(theflip->rotation>=ANGLES)    theflip->rotation-=ANGLES;
  154.     theflip->mirror= !theflip->mirror;
  155.  
  156.     if(theflip->level.i==0)
  157.         Hero.lanestat[LaneSel[theflip->vertex][theflip->rotation]] |= FlipMask;
  158. }
  159. /*
  160. >>    This routine is called for each active flipper.
  161. >>    An active flipper has gone through the star
  162. >>    phase and now rotates and climbs up.
  163. */
  164. void        UpdateActiveFlipper(theflip)
  165. register
  166. FlipperPtr    theflip;
  167. {
  168.     register    int        dx,dy,x,y;
  169.                 int        sc;
  170.                 int        doskip;
  171.  
  172.     theflip->level.f-=FLIPPERUPSPEED;    /*    Move up a bit.                        */
  173.     if(theflip->level.i<=0)                /*    Don't move past the top.            */
  174.     {    theflip->level.i=0;
  175.         ThisLevel.edgeCount++;            /*    Flipper is on the edge.                */
  176.     }
  177.  
  178.     y=theflip->direction;    /*    I find this ugly, but it needs to be fast.        */
  179.  
  180.     while(y)                /*    While there is rotation to be done.                */
  181.     {    x=theflip->rotation;/*    x is now the current rotation value.            */
  182.         dx=NextSeg[theflip->vertex]-x;    /*    Find next clockwise vertex angle.    */
  183.         dy=PrevSeg[theflip->vertex]-x;    /*    Find next counter-cw vertex angle.    */
  184.                                 /*    Note that the above angles are relative!    */
  185.  
  186.         if(dx<-ANGLES)    dx=y+y;    /*    A negative angle is used as a flag value    */
  187.         if(dy<-ANGLES)    dy=y+y;    /*    to indicate that there is no "next vertex".    */
  188.  
  189.         if(y>0)                        /*    Clockwise rotation?                        */
  190.         {    if(dx<=0)    dx+=ANGLES;    /*    Force angle between 1 and ANGLES        */
  191.             if(dy<=0)    dy+=ANGLES;    /*    Same thing here.                        */
  192.             if(dx<dy)                /*    Which vertex is next?                    */
  193.             {    if(y>=dx)            /*    Can we reach the next clockwise vertex?    */
  194.                 {    y-=dx;            /*    Yes, adjust the rotation left to do.    */
  195.                     theflip->rotation+=dx;    /*    Rotate to this vertex.            */
  196.                     theflip->vertex++;        /*    Increment vertex value.            */
  197.  
  198.                     doskip= 1;        /*    We skipped from a vertex to another.    */
  199.                     if(ww.wraps)    /*    Following code depends on field type.    */
  200.                     {    if(theflip->vertex>=ww.numsegs)
  201.                         {    theflip->vertex=0;    /*    Wrap around to other side.    */
  202.                         }
  203.                     }
  204.                     else    /*    Bounce back, if hit the edge of the playfield.    */
  205.                     {    if(theflip->vertex>=ww.numsegs)
  206.                         {    theflip->vertex=ww.numsegs-1;
  207.                             theflip->direction= -theflip->direction;
  208.                             y= -y;
  209.                             doskip= 0;
  210.                             if(theflip->level.i==0)
  211.                                 Hero.lanestat[theflip->vertex] |= FlipMask;
  212.                         }
  213.                     }
  214.                     if(doskip)        /*    Did we grab a new vertex?                */
  215.                         SegSkip(theflip);
  216.                 }
  217.                 else    /*    Didn't reach a new vertex. No more rotating to do.    */
  218.                 {    theflip->rotation+=y;
  219.                     y=0;
  220.                 }
  221.             }
  222.             else            /*    Basically the same code as above follows,        */
  223.             {    if(y>=dy)    /*     but in the other direction.                    */
  224.                 {    y-=dy;
  225.                     theflip->rotation+=dy;
  226.                     theflip->vertex--;
  227.                     doskip= 1;
  228.                     
  229.                     if(ww.wraps)
  230.                     {    if(theflip->vertex<0)
  231.                         {    theflip->vertex=ww.numsegs-1;
  232.                         }
  233.                     }
  234.                     else
  235.                     {    if(theflip->vertex==0)
  236.                         {    theflip->vertex=1;
  237.                             theflip->direction= -theflip->direction;
  238.                             y= -y;
  239.                             doskip= 0;
  240.                             if(theflip->level.i==0)
  241.                                 Hero.lanestat[0] |= FlipMask;
  242.                         }
  243.                     }
  244.                     if(doskip)
  245.                         SegSkip(theflip);
  246.                 }
  247.                 else
  248.                 {    theflip->rotation+=y;
  249.                     y=0;
  250.                 }
  251.             }
  252.             /*    Adjust rotation angle to be between 0 and ANGLES-1.                */
  253.             if(theflip->rotation>=ANGLES) theflip->rotation-=ANGLES;
  254.         }
  255.         else    /*    Counterclockwise rotation. Otherwise similar to above code.    */
  256.         {    if(dx>=0)    dx-=ANGLES;
  257.             if(dy>=0)    dy-=ANGLES;
  258.             if(dx>dy)
  259.             {    if(y<=dx)
  260.                 {    y-=dx;
  261.                     theflip->rotation+=dx;
  262.                     theflip->vertex++;
  263.                     
  264.                     doskip= 1;
  265.                     if(ww.wraps)
  266.                     {    if(theflip->vertex>=ww.numsegs)
  267.                         {    theflip->vertex=0;
  268.                         }
  269.                     }
  270.                     else
  271.                     {    if(theflip->vertex>=ww.numsegs)
  272.                         {    theflip->vertex=ww.numsegs-1;
  273.                             theflip->direction= -theflip->direction;
  274.                             y= -y;
  275.                             doskip= 0;
  276.                             if(theflip->level.i==0)
  277.                                 Hero.lanestat[theflip->vertex] |= FlipMask;
  278.                         }
  279.                     }
  280.                     if(doskip)
  281.                         SegSkip(theflip);
  282.                 }
  283.                 else    
  284.                 {    theflip->rotation+=y;
  285.                     y=0;
  286.                 }
  287.             }
  288.             else
  289.             {    if(y<=dy)
  290.                 {    y-=dy;
  291.                     theflip->rotation+=dy;
  292.                     theflip->vertex--;
  293.                     doskip= 1;
  294.                     
  295.                     if(ww.wraps)
  296.                     {    if(theflip->vertex<0)
  297.                         {    theflip->vertex=ww.numsegs-1;
  298.                         }
  299.                     }
  300.                     else
  301.                     {    if(theflip->vertex==0)
  302.                         {    theflip->vertex=1;
  303.                             theflip->direction= -theflip->direction;
  304.                             y= -y;
  305.                             doskip= 0;
  306.                             if(theflip->level.i==0)
  307.                                 Hero.lanestat[0] |= FlipMask;
  308.                         }
  309.                     }
  310.                     if(doskip)
  311.                         SegSkip(theflip);
  312.                 }
  313.                 else
  314.                 {    theflip->rotation+=y;
  315.                     y=0;
  316.                 }
  317.             }
  318.             if(theflip->rotation<0)    theflip->rotation+=ANGLES;
  319.         }
  320.     }
  321.  
  322.     /*    Find out the lane that we belong to currently.    This depends
  323.     **    on the vertex we are connected to and the angle at which we
  324.     **    are hanging.
  325.     */
  326.     theflip->lane=LaneSel[theflip->vertex][theflip->rotation];
  327.  
  328.     /*    Calculate the position and width of the flipper.                */
  329.     dx= ww.unitlen[theflip->level.i];    /*    Look up length at this level.*/
  330.     
  331.     dy= (dx*(long) -Sins[theflip->rotation])>>8;    /*    Fixed point rotation.    */
  332.     dx= (dx*(long)Cosins[theflip->rotation])>>8;
  333.  
  334.     x=ww.x[theflip->vertex][theflip->level.i];/*    Find position on screen.*/
  335.     y=ww.y[theflip->vertex][theflip->level.i];
  336.     
  337.     if(!VA.Late)                /*    Is there time to draw something?    */
  338.     {    if(theflip->mirror)        /*    Is the flipper mirrored?            */
  339.             DrawFlipper(x+dx,y+dy,-dx,-dy);
  340.         else
  341.             DrawFlipper(x,y,dx,dy);
  342.     }
  343.  
  344.     /*    Notify the player record if a flipper is on the edge.            */
  345.     if(theflip->level.i==0)
  346.     {    Hero.segmstat[theflip->vertex] |= FlipMask;
  347.     }
  348.     
  349.     /*    Test to see if the player has hit us.                            */
  350.     if(ShotHitTest(theflip->lane,theflip->level.i))
  351.     {    sc=ww.unitlen[theflip->level.i];        /*    Explode into two parts.    */
  352.         AddCrack(    x,y,
  353.                     -dx >> 3,-dy >> 3,
  354.                     FLIPPERCOLOR,sc,FlipperLeft,
  355.                     theflip->rotation,theflip->direction,20);
  356.         AddCrack(    x+dx,y+dy,
  357.                     dx >> 3,dy >> 3,
  358.                     FLIPPERCOLOR,sc,FlipperRight,
  359.                     theflip->rotation+ANGLES/2,theflip->direction,20);
  360.         PlayB(Swoosh,10);
  361.  
  362.         ThisLevel.flCount--;
  363.         ThisLevel.totalCount--;
  364.  
  365.         IncreaseScore(ThisLevel.flPoints);
  366.         theflip->state=inactive;
  367.         ActiveFlippers--;
  368.     }
  369. }
  370.  
  371. /*
  372. >>    Go through the flippers checking their state and
  373. >>    promoting them from stars to fully grown flipper,
  374. >>    when they reach the playfield.
  375. */
  376. void    UpdateFlippers()
  377. {
  378.     register    Flipper        *flp;
  379.     register    int            i;
  380.     
  381.     flp=Flippers;
  382.     for(i=0;i<MAXFLIPPERS;i++)
  383.     {    if(flp->state<0)
  384.         {    flp->vertex= -(flp->state + 1)/STARDIVISION;
  385.             flp->state= active;
  386.             if(!ww.wraps && flp->vertex==0)    flp->vertex=1;
  387.             if(flp->vertex>ww.numsegs)        flp->vertex=ww.numsegs;
  388.  
  389.             if(flp->direction < 0)
  390.             {    flp->rotation=NextSeg[flp->vertex];
  391.             }
  392.             else
  393.             {    flp->rotation=PrevSeg[flp->vertex];
  394.             }
  395.         }
  396.         else
  397.         {    if(flp->state==active)
  398.                 UpdateActiveFlipper(flp);
  399.         }
  400.         flp++;
  401.     }
  402.  
  403.     if(ActiveFlippers<MAXFLIPPERS && ThisLevel.flCount>ActiveFlippers)
  404.     {    if(VAPosRandom() < ThisLevel.flProb+ThisLevel.probIncrease)
  405.         {    CreateNewFlipper();
  406.         }
  407.     }
  408.     
  409.     ThisLevel.starCount += ThisLevel.flCount-ActiveFlippers;
  410.     ThisLevel.activeCount += ActiveFlippers;
  411. }
  412.  
  413. void    InitFlippers()
  414. {
  415.     register    int        i;
  416.     
  417.     for(i=0;i<MAXFLIPPERS;i++)
  418.     {    Flippers[i].state=inactive;
  419.     }
  420.     ActiveFlippers=0;
  421. }
  422.  
  423. void    AllocFlippers()
  424. {
  425.     Flippers=(Flipper *)NewPtr(sizeof(Flipper)*MAXFLIPPERS);
  426. }
  427.